package top.wjgyy.tools.ddns.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.alidns.model.v20150109.*;
import com.aliyuncs.domain.model.v20180129.QueryDomainListRequest;
import com.aliyuncs.domain.model.v20180129.QueryDomainListResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.aliyuncs.utils.StringUtils;
import org.apache.commons.compress.utils.IOUtils;

public class DDNSService {
    private static DDNSService instance;
    private  static  IAcsClient client;
    private String regionId = "cn-shanghai";
    // "LTAI5tCuGgW7ZTGCCbn4T31H"
    //"zYbm9qaT2WZF5TFteBY7v1VnHyRUdd"


    public static IAcsClient getClient() {
        return client;
    }

    /**
     * 初始化阿里API请求并连接
     * @param accessKeyId
     * @param secret
     * @return
     */
    public static DDNSService getInstance(String accessKeyId, String secret){
        if (instance == null && (StringUtils.isEmpty(accessKeyId) && StringUtils.isEmpty(secret))) throw new RuntimeException("无法初始化阿里API服务！");
        instance = instance == null ? new DDNSService(accessKeyId, secret) : instance;
        return instance;
    }

    public DDNSService(String accessKeyId, String secret) {
        DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, secret);
        client = new DefaultAcsClient(profile);
    }

    /**
     * 获取域名解析结果
     * @param host
     * @param type
     * @return
     */
    public DescribeSubDomainRecordsResponse.Record getRecodesByHost(String host, String type) {
        if (StrUtil.hasBlank(host) || StrUtil.hasBlank(type)) {
            return null;
        }
        DescribeSubDomainRecordsRequest request = new DescribeSubDomainRecordsRequest();
        request.setSubDomain(host);

        DescribeSubDomainRecordsResponse response;

        try {
            response = client.getAcsResponse(request);
            List<DescribeSubDomainRecordsResponse.Record> domainRecords = response.getDomainRecords();
            for (DescribeSubDomainRecordsResponse.Record domainRecord : domainRecords) {
                if (type.toUpperCase().equals(domainRecord.getType())) {
                    return domainRecord;
                }
            }
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
        return null;
    }

    /**
     * 获取域名的二级域名
     * @param host
     * @return
     */
    public String getSecondaryDomain(String host) {
        int lastDelimiter = host.lastIndexOf(".", host.lastIndexOf(".") - 1);
        return host.substring(0, lastDelimiter);
    }


    /**
     * 获取账户下的域名列表
     * @return
     * @throws ClientException
     */
    public List<QueryDomainListResponse.Domain> getDomainList() throws ClientException {
        QueryDomainListRequest request = new QueryDomainListRequest();
        request.setPageNum(0);
        request.setPageSize(1000);
        QueryDomainListResponse response = client.getAcsResponse(request);
        return response.getData();
    }

    /**
     * 获取域名解析列表
     * @return
     * @throws ClientException
     */
    public List<DescribeDomainRecordsResponse.Record> getDescribeDomainRecordsList(String domainName) throws ClientException {
        DescribeDomainRecordsRequest request = new DescribeDomainRecordsRequest();
        request.setDomainName(domainName);
        DescribeDomainRecordsResponse response = client.getAcsResponse(request);
        return response.getDomainRecords();
    }


    /**
     * 获取当前主机公网IPv4地址
     */
    public String getCurrentHostIPv4(){
        // 这里使用jsonip.com第三方接口获取本地IP
        String jsonip = "https://jsonip.com/";
        // 接口返回结果
        String result = "";
        BufferedReader in = null;
        try {
            // 使用HttpURLConnection网络请求第三方接口
            URL url = new URL(jsonip);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();
            in = new BufferedReader(new InputStreamReader(
                    urlConnection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }

        }
        // 正则表达式，提取xxx.xxx.xxx.xxx，将IP地址从接口返回结果中提取出来
        String rexp = "(\\d{1,3}\\.){3}\\d{1,3}";
        Pattern pat = Pattern.compile(rexp);
        Matcher mat = pat.matcher(result);
        String res="";
        while (mat.find()) {
            res=mat.group();
            break;
        }
        return res;
    }

    /**
     * 获取当前主机公网IPv6地址
     */
    public String getCurrentHostIPv6(){
        // 这里使用jsonip.com第三方接口获取本地IP
        String jsonip = "https://ipv6.jsonip.com/";
        // String jsonip = "http://ipv6.lookup.test-ipv6.com/ip/?callback=_jqjsp&asn=1&testdomain=test-ipv6.com&testname=test_asn6";
        // 接口返回结果
        String result = "";
        BufferedReader in = null;
        try {
            // 使用HttpURLConnection网络请求第三方接口
            URL url = new URL(jsonip);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();
            in = new BufferedReader(new InputStreamReader(
                    urlConnection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }

        }
        // 正则表达式，提取xxx.xxx.xxx.xxx，将IP地址从接口返回结果中提取出来
        String rexp = "[a-f0-9]{1,4}((:[a-f0-9]{1,4}){7})";
        Pattern pat = Pattern.compile(rexp);
        Matcher mat = pat.matcher(result);
        String res="";
        while (mat.find()) {
            res=mat.group();
            break;
        }
        return res;
    }

    /**
     * 通过CMD命令获取当前主机公网IPv6地址
     */
    public String getCurrentHostIPv6ForCMD(){
        String pattern = "[a-f0-9]{1,4}((:[a-f0-9]{1,4}){7})";
        String res = "";
        InputStream is = null;
        try {
            Process process = Runtime.getRuntime().exec("cmd /c " + "ipconfig");
            is = process.getInputStream();
            String s = new String(IOUtils.toByteArray(is), "GBK");
            Pattern compile = Pattern.compile(pattern);
            Matcher matcher = compile.matcher(s);
            while (matcher.find()) {
                res = matcher.group();
            }
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        // 正则表达式，提取xxx.xxx.xxx.xxx，将IP地址从接口返回结果中提取出来
        return res;
    }

    /**
     * 修改IP解析记录
     * @param host
     * @param value
     * @return
     */
    public String updateBindIp(String host, String value) {
        DescribeSubDomainRecordsResponse.Record record = getRecodesByHost(host, "A");
        if (record == null) {
            return "当前DNS不存在";
        }
        String secondaryDomain = getSecondaryDomain(host);
        UpdateDomainRecordRequest request = new UpdateDomainRecordRequest();
        request.setRecordId(record.getRecordId());
        request.setRR(secondaryDomain);
        request.setType("A");
        request.setValue(value);

        try {
            UpdateDomainRecordResponse response = client.getAcsResponse(request);
            return "success";
        } catch (ServerException e) {
            e.printStackTrace();
            return "error";
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
            return e.getErrMsg();
        }
    }


    public String updateBindIp(String domainName, String rR, String type, String currentHostIP){
        try {
            // 查询指定二级域名的最新解析记录
            DescribeDomainRecordsRequest describeDomainRecordsRequest = new DescribeDomainRecordsRequest();
            // 主域名
            describeDomainRecordsRequest.setDomainName(domainName);
            // 主机记录
            describeDomainRecordsRequest.setRRKeyWord(rR);
            // 解析记录类型
            describeDomainRecordsRequest.setType(type);
            DescribeDomainRecordsResponse describeDomainRecordsResponse = client.getAcsResponse(describeDomainRecordsRequest);

            List<DescribeDomainRecordsResponse.Record> domainRecords = describeDomainRecordsResponse.getDomainRecords();
            // 最新的一条解析记录
            if (domainRecords.size() != 0) {
                DescribeDomainRecordsResponse.Record record = domainRecords.get(0);
                // 记录ID
                String recordId = record.getRecordId();
                // 记录值
                String recordsValue = record.getValue();
                // 当前主机公网IP
                System.out.println("-------------------------------当前主机公网IP为：" + currentHostIP + "-------------------------------");
                if (currentHostIP.equals(recordsValue)) return "DDNS无需刷新，当前ip为：" + currentHostIP;
                    // 修改解析记录
                UpdateDomainRecordRequest updateDomainRecordRequest = new UpdateDomainRecordRequest();
                // 主机记录
                updateDomainRecordRequest.setRR(rR);
                // 记录ID
                updateDomainRecordRequest.setRecordId(recordId);
                // 将主机记录值改为当前主机IP
                updateDomainRecordRequest.setValue(currentHostIP);
                // 解析记录类型
                updateDomainRecordRequest.setType(type);
                UpdateDomainRecordResponse response = client.getAcsResponse(updateDomainRecordRequest);
                return JSON.toJSONString(response);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "DDNS处理异常：" + e.getMessage();
        }
        return "";
    }
}
